<?php

namespace handle\message\lib\base;

use Workerman\Connection\TcpConnection;

class MainCenter
{
    /**
     * 数据
     * @var array
     */
    protected array $data = [];

    protected string $mode;

    private string $key = WEBSOCKET_PRIVATE_KEY;

    protected bool $isSign = true;

    protected string $rawData = '';

    protected TcpConnection $connection;

    public function validateData(string $data): void
    {
        $this->rawData = $data;
        /**
         * $data = [
         *       messageType: '',
         *       data: [...],
         *       sign: '',
         *       timestamp: '',
         *  ]
         */
        $data = is_array(json_decode($data, true)) ? json_decode($data, true) : [];
        if($this->verify($data)){
            $this->getData($data);
        }else{
            $this->isSign = false;
            $this->recordErrorSign();
            $this->connection->send(sendMsg('你的通行证无效哦!!!')); //发送提示信息
        }
    }

    /**
     * 获取数据
     * @param $data
     * @return void
     */
    private function getData($data)
    {
        $this->mode = $data['messageType'];
        unset($data['messageType']);
        (isset($data['room_id']) and !empty($data['room_id'])) and $data['room_id'] = md5($data['room_id']);
        $this->data = $data['data'];
    }

    /**
     * 验证签名
     * @param array $data
     * @return bool
     */
    private function verify(array $data): bool
    {
        if($this->checkDataEmpty($data)){
            return false;
        }
        if(time() - $data['timestamp'] > WEBSOCKET_SIGN_TIME_OUT){ //签名超时了
            return false;
        }
        return md5($this->getUrlString($data) . $this->key) === $data['sign'];
    }

    private function getUrlString(array $data): string
    {
        if(empty($data)){
            return '';
        }
        if(isset($data['sign'])){
            unset($data['sign']);
        }
        $data = arrayMultiKeyRsort($data);
        return $this->makeUrlString($data);
    }

    /**
     * 获取url字符串
     * @param array $data
     * @param string $prefix
     * @return string
     */
    private function makeUrlString(array $data, string $prefix = ''): string
    {
        $url = '';
        foreach($data as $k => $v){
            if($v === null or $v === '')continue;
            if(is_array($v)){
                $url .= $this->makeUrlString($v, $prefix . $k. '.') ;
            }else{
                $url .= $prefix . $k . '=' . $v . '&';
            }
        }
        return !$prefix ? substr($url, 0, -1) : $url;
    }


    /**
     * 判断数据是否为空
     * @param array $data
     * @return bool
     */
    private function checkDataEmpty(array $data): bool
    {
        return (empty($data) or !isset($data['sign']) or !isset($data['timestamp']) or !isset($data['data']) or empty($data['sign']) or empty($data['timestamp']) or empty($data['data']));
    }

    private function recordErrorSign(): void
    {
        $dataUrl = $this->getUrlString(is_array(json_decode($this->rawData, true)) ? json_decode($this->rawData, true) : []);
        workerMessage('签名不通过!' . PHP_EOL . '原始数据[\'' . $this->rawData . '\'] ' . PHP_EOL . '服务器数据链[\'' . $dataUrl . '\']' . PHP_EOL . '服务器数据签名[\'' . md5($dataUrl . $this->key) . '\']', '/sign');
    }

    /**
     * 响应错误
     * @param string $msg
     * @return void
     */
    protected function responseError(string $msg){
        $this->connection->send(sendMsg($msg, 'error'));
    }

}